{ "cells": [ { "cell_type": "markdown", "id": "bbbaafbb-fd7d-4b73-a970-93506ba35d71", "metadata": { "tags": [] }, "source": [ "# Example use case: Common-envelope evolution\n", "\n", "In this notebook we look at how common-envelope evolution (CEE) alters binary-star orbits. We construct a population of low- and intermediate-mass binaries and compare their orbital periods before and after CEE. Not all stars evolve into this phase, so we have to run a whole population to find those that do. We then have to construct the pre- and post-CEE distributions and plot them.\n", "\n", "First, we import a few required Python modules. " ] }, { "cell_type": "code", "execution_count": 1, "id": "bf6b8673-a2b5-4b50-ad1b-e90671f57470", "metadata": {}, "outputs": [], "source": [ "import os\n", "import math\n", "import matplotlib.pyplot as plt\n", "from binarycpython.utils.functions import temp_dir, output_lines\n", "from binarycpython import Population\n", "\n", "TMP_DIR = temp_dir(\"notebooks\", \"notebook_comenv\", clean_path=True)\n", "VERBOSITY = 2" ] }, { "cell_type": "markdown", "id": "f268eff3-4e08-4f6b-8b59-f22dba4d2074", "metadata": { "tags": [] }, "source": [ "## Setting up the Population object\n", "We set up a new population object. Our stars evolve to $13.7\\text{ }\\mathrm{Gyr}$, the age of the Universe, and we assume the metallicity $Z=0.02$. We also set the common-envelope ejection efficiency $\\alpha_\\mathrm{CE}=1$ and the envelope structure parameter $\\lambda=0.5$. More complex options are available in *binary_c*, such as $\\lambda$ based on stellar mass, but this is just a demonstration example so let's keep things simple." ] }, { "cell_type": "code", "execution_count": 2, "id": "79ab50b7-591f-4883-af09-116d1835a751", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "adding: log_dt=10 to population_options\n", "adding: max_evolution_time=13700 to BSE_options\n", "adding: metallicity=0.02 to BSE_options\n", "adding: alpha_ce=1.0 to BSE_options\n", "adding: lambda_ce=0.5 to BSE_options\n" ] } ], "source": [ "# Create population object\n", "population = Population(tmp_dir=TMP_DIR, verbosity=VERBOSITY)\n", "population.set(\n", " # grid options\n", " log_dt = 10, # log progress every 10 seconds\n", "\n", " # binary-star evolution options\n", " max_evolution_time=13700, # maximum stellar evolution time in Myr (13700 Myr == 13.7 Gyr)\n", " metallicity=0.02, # 0.02 is approximately Solar metallicity \n", " alpha_ce = 1.0,\n", " lambda_ce = 0.5,\n", ")" ] }, { "cell_type": "markdown", "id": "f9a65554-36ab-4a04-96ca-9f1422c307fd", "metadata": {}, "source": [ "## Stellar Grid\n", "We now construct a grid of stars, varying the mass from $1$ to $6\\text{ }\\mathrm{M}_\\odot$. We avoid massive stars for now, and focus on the (more common) low- and intermediate-mass stars. We also limit the period range to $10^4\\text{ }\\mathrm{d}$ because systems with longer orbital periods will probably not undergo Roche-lobe overflow and hence common-envelope evolution is impossible." ] }, { "cell_type": "code", "execution_count": 3, "id": "47979841-2c26-4b26-8945-603d013dc93a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Added sampling variable: {\n", " \"name\": \"lnm1\",\n", " \"parameter_name\": \"M_1\",\n", " \"longname\": \"Primary mass\",\n", " \"valuerange\": [\n", " 1,\n", " 6\n", " ],\n", " \"samplerfunc\": \"self.const_linear(math.log(1), math.log(6), 10)\",\n", " \"precode\": \"M_1=math.exp(lnm1)\",\n", " \"postcode\": null,\n", " \"probdist\": \"self.three_part_powerlaw(M_1, 0.1, 0.5, 1.0, 150, -1.3, -2.3, -2.3)*M_1\",\n", " \"dphasevol\": \"dlnm1\",\n", " \"condition\": \"\",\n", " \"gridtype\": \"centred\",\n", " \"branchpoint\": 0,\n", " \"branchcode\": null,\n", " \"topcode\": null,\n", " \"bottomcode\": null,\n", " \"sampling_variable_number\": 0,\n", " \"dry_parallel\": false,\n", " \"dependency_variables\": null\n", "}\n", "Added sampling variable: {\n", " \"name\": \"q\",\n", " \"parameter_name\": \"M_2\",\n", " \"longname\": \"Mass ratio\",\n", " \"valuerange\": [\n", " \"0.1/M_1\",\n", " 1\n", " ],\n", " \"samplerfunc\": \"self.const_linear(1/M_1, 1, 10)\",\n", " \"precode\": \"M_2 = q * M_1\",\n", " \"postcode\": null,\n", " \"probdist\": \"self.flatsections(q, [{'min': 1/M_1, 'max': 1.0, 'height': 1}])\",\n", " \"dphasevol\": \"dq\",\n", " \"condition\": \"\",\n", " \"gridtype\": \"centred\",\n", " \"branchpoint\": 0,\n", " \"branchcode\": null,\n", " \"topcode\": null,\n", " \"bottomcode\": null,\n", " \"sampling_variable_number\": 1,\n", " \"dry_parallel\": false,\n", " \"dependency_variables\": null\n", "}\n", "Added sampling variable: {\n", " \"name\": \"log10per\",\n", " \"parameter_name\": \"orbital_period\",\n", " \"longname\": \"log10(Orbital_Period)\",\n", " \"valuerange\": [\n", " 0.15,\n", " 5.5\n", " ],\n", " \"samplerfunc\": \"self.const_linear(0.15, 4, 10)\",\n", " \"precode\": \"orbital_period = 10.0 ** log10per\\nsep = calc_sep_from_period(M_1, M_2, orbital_period)\\nsep_min = calc_sep_from_period(M_1, M_2, 10**0.15)\\nsep_max = calc_sep_from_period(M_1, M_2, 10**4)\",\n", " \"postcode\": null,\n", " \"probdist\": \"self.sana12(M_1, M_2, sep, orbital_period, sep_min, sep_max, math.log10(10**0.15), math.log10(10**4), -0.55)\",\n", " \"dphasevol\": \"dlog10per\",\n", " \"condition\": null,\n", " \"gridtype\": \"centred\",\n", " \"branchpoint\": 0,\n", " \"branchcode\": null,\n", " \"topcode\": null,\n", " \"bottomcode\": null,\n", " \"sampling_variable_number\": 2,\n", " \"dry_parallel\": false,\n", " \"dependency_variables\": null\n", "}\n" ] } ], "source": [ "# Set resolution and mass range that we simulate\n", "resolution = {\"M_1\": 10, \"q\" : 10, \"per\": 10} \n", "massrange = [1, 6] \n", "logperrange = [0.15, 4]\n", "\n", "population.add_sampling_variable(\n", " name=\"lnm1\",\n", " longname=\"Primary mass\",\n", " valuerange=massrange,\n", " samplerfunc=\"self.const_linear(math.log({min}), math.log({max}), {res})\".format(min=massrange[0],max=massrange[1],res=resolution[\"M_1\"]),\n", " precode=\"M_1=math.exp(lnm1)\",\n", " probdist=\"self.three_part_powerlaw(M_1, 0.1, 0.5, 1.0, 150, -1.3, -2.3, -2.3)*M_1\",\n", " dphasevol=\"dlnm1\",\n", " parameter_name=\"M_1\",\n", " condition=\"\", # Impose a condition on this grid variable. Mostly for a check for yourself\n", ")\n", "\n", "# Mass ratio\n", "population.add_sampling_variable(\n", " name=\"q\",\n", " longname=\"Mass ratio\",\n", " valuerange=[\"0.1/M_1\", 1],\n", " samplerfunc=\"self.const_linear({}/M_1, 1, {})\".format(massrange[0],resolution['q']),\n", " probdist=\"self.flatsections(q, [{{'min': {}/M_1, 'max': 1.0, 'height': 1}}])\".format(massrange[0]),\n", " dphasevol=\"dq\",\n", " precode=\"M_2 = q * M_1\",\n", " parameter_name=\"M_2\",\n", " condition=\"\", # Impose a condition on this grid variable. Mostly for a check for yourself\n", ")\n", "\n", "# Orbital period\n", "population.add_sampling_variable(\n", " name=\"log10per\", # in days\n", " longname=\"log10(Orbital_Period)\",\n", " valuerange=[0.15, 5.5],\n", " samplerfunc=\"self.const_linear({}, {}, {})\".format(logperrange[0],logperrange[1],resolution[\"per\"]),\n", " precode=\"\"\"orbital_period = 10.0 ** log10per\n", "sep = calc_sep_from_period(M_1, M_2, orbital_period)\n", "sep_min = calc_sep_from_period(M_1, M_2, 10**{})\n", "sep_max = calc_sep_from_period(M_1, M_2, 10**{})\"\"\".format(logperrange[0],logperrange[1]),\n", " probdist=\"self.sana12(M_1, M_2, sep, orbital_period, sep_min, sep_max, math.log10(10**{}), math.log10(10**{}), {})\".format(logperrange[0],logperrange[1],-0.55),\n", " parameter_name=\"orbital_period\",\n", " dphasevol=\"dlog10per\",\n", ")" ] }, { "cell_type": "markdown", "id": "163f13ae-fec1-4ee8-b9d4-c1b75c19ff39", "metadata": {}, "source": [ "## Logging and handling the output\n", "\n", "We now construct the pre- and post-common envelope evolution data for the first common envelope that forms in each binary. We look at the comenv_count variable, we can see that when it increases from 0 to 1 we have found our object. If this happens, we stop evolution of the system to save CPU time." ] }, { "cell_type": "code", "execution_count": 4, "id": "0c986215-93b1-4e30-ad79-f7c397e9ff7d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "adding: C_logging_code=\n", "\n", "/*\n", " * Detect when the comenv_count increased \n", " */\n", "if(stardata->model.comenv_count == 1 && \n", " stardata->previous_stardata->model.comenv_count == 0)\n", "{\n", " /*\n", " * We just had this system's first common envelope:\n", " * output the time at which this happens, \n", " * the system's probability (proportional to the number of stars),\n", " * the previous timestep's (pre-comenv) orbital period (days) and\n", " * the current timestep (post-comenv) orbital period (days)\n", " */\n", " Printf(\"COMENV %g %g %g %g\\n\",\n", " stardata->model.time,\n", " stardata->model.probability,\n", " stardata->previous_stardata->common.orbit.period * YEAR_LENGTH_IN_DAYS,\n", " stardata->common.orbit.period * YEAR_LENGTH_IN_DAYS);\n", " \n", " /*\n", " * We should waste no more CPU time on this system now we have the\n", " * data we want.\n", " */\n", " stardata->model.evolution_stop = TRUE;\n", "}\n", " to population_options\n" ] } ], "source": [ "custom_logging_statement = \"\"\"\n", "\n", "/*\n", " * Detect when the comenv_count increased \n", " */\n", "if(stardata->model.comenv_count == 1 && \n", " stardata->previous_stardata->model.comenv_count == 0)\n", "{\n", " /*\n", " * We just had this system's first common envelope:\n", " * output the time at which this happens, \n", " * the system's probability (proportional to the number of stars),\n", " * the previous timestep's (pre-comenv) orbital period (days) and\n", " * the current timestep (post-comenv) orbital period (days)\n", " */\n", " Printf(\"COMENV %g %g %g %g\\\\n\",\n", " stardata->model.time,\n", " stardata->model.probability,\n", " stardata->previous_stardata->common.orbit.period * YEAR_LENGTH_IN_DAYS,\n", " stardata->common.orbit.period * YEAR_LENGTH_IN_DAYS);\n", " \n", " /*\n", " * We should waste no more CPU time on this system now we have the\n", " * data we want.\n", " */\n", " stardata->model.evolution_stop = TRUE;\n", "}\n", "\"\"\"\n", "\n", "population.set(\n", " C_logging_code=custom_logging_statement\n", ")" ] }, { "cell_type": "markdown", "id": "ae1f1f0c-1f8b-42d8-b051-cbf8c6b51514", "metadata": {}, "source": [ "The parse function must now catch lines that start with \"COMENV\" and process the associated data. We set up the parse_data function to do just this." ] }, { "cell_type": "code", "execution_count": 5, "id": "fd197154-a8ce-4865-8929-008d3483101a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "adding: parse_function= to population_options\n" ] } ], "source": [ "from binarycpython.utils.functions import bin_data, datalinedict\n", "import re\n", "\n", "# log-period distribution bin width (dex)\n", "binwidth = 0.5 \n", "\n", "def parse_function(self, output):\n", " \"\"\"\n", " Parsing function to convert HRD data into something that Python can use\n", " \"\"\"\n", " \n", " # list of the data items\n", " parameters = [\"header\", \"time\", \"probability\", \"pre_comenv_period\", \"post_comenv_period\"]\n", " \n", " # Loop over the output.\n", " for line in output_lines(output):\n", " # obtain the line of data in dictionary form \n", " linedata = datalinedict(line,parameters)\n", "\n", " # choose COMENV lines of output\n", " if linedata[\"header\"] == \"COMENV\":\n", " # bin the pre- and post-comenv log10-orbital-periods to nearest 0.5dex\n", " binned_pre_period = bin_data(math.log10(linedata[\"pre_comenv_period\"]), binwidth)\n", " \n", " # but check if the post-comenv period is finite and positive: if \n", " # not, the system has merged and we give it an aritifical period\n", " # of 10^-100 days (which is very much unphysical)\n", " if linedata[\"post_comenv_period\"] > 0.0:\n", " binned_post_period = bin_data(math.log10(linedata[\"post_comenv_period\"]), binwidth)\n", " else:\n", " binned_post_period = bin_data(-100,binwidth) # merged!\n", " \n", " # make the \"histograms\"\n", " self.population_results['pre'][binned_pre_period] += linedata[\"probability\"]\n", " self.population_results['post'][binned_post_period] += linedata[\"probability\"]\n", " \n", " # verbose reporting\n", " #print(\"parse out results_dictionary=\",self.population_results)\n", " \n", "# Add the parsing function\n", "population.set(\n", " parse_function=parse_function,\n", ")" ] }, { "cell_type": "markdown", "id": "91509ce5-ffe7-4937-aa87-6d7baac9ac04", "metadata": {}, "source": [ "## Evolving the grid\n", "Now we actually run the population. This may take a little while. You can set num_cores higher if you have a powerful machine." ] }, { "cell_type": "code", "execution_count": 6, "id": "8ea376c1-1e92-45af-8cab-9d7fdca564eb", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "adding: num_cores=4 to population_options\n", "adding: verbosity=2 to population_options\n", "Creating the code for the shared library for the custom logging\n", "File/directory /tmp/binary_c_python-david/notebooks/notebook_comenv/custom_logging/custom_logging.c doesn't exist. Can't remove it.\n", "Writing the custom logging code to /tmp/binary_c_python-david/notebooks/notebook_comenv/custom_logging/custom_logging.c\n", "File/directory /tmp/binary_c_python-david/notebooks/notebook_comenv/custom_logging/libcustom_logging_c2c13e8068bc4385b960647d0028913e.so doesn't exist. Can't remove it.\n", "Calling the binary_c config code to get the info to build the shared library\n", "Got options to compile:\n", "\tcc = cc\n", "\tccflags = -std=gnu18 -DOPERATING_SYSTEM=linux -DLINUX -DPOSIX -DLARGEFILE_SOURCE -DMEMORY_ALLOCATION_MODEL=MEMORY_ALLOCATION_NATIVE -UALIGNSIZE -fstrict-aliasing -Wstrict-aliasing -g -Wno-sizeof-pointer-div -Wpedantic -Wshadow -Wno-variadic-macros -fstack-protector-all -rdynamic -fsignaling-nans -march=native -mtune=native -frounding-math -fno-stack-protector -ffloat-store -D__ACCURATE_BINARY_C__ -fno-finite-math-only -fasynchronous-unwind-tables -export-dynamic -O0 -DCPUFREQ=4500 -DBINARY_C_SRC=/home/david/projects/binary_c_root/binary_c/src -DPGO_off -DBINUTILS_VERSION=2.34 -DBFD_2_33 -D_FILE_OFFSET_BITS=64 -D__HAVE_LINK_H -D__HAVE__VA_OPT__ -D__HAVE_GNU_QSORT_R -D__HAVE_NATIVE_EXP10 -D__HAVE_POSIX_FADVISE -DFPU_CONTROL -D__HAVE_ATTRIBUTE___RESTRICT____ -D__HAVE_ATTRIBUTE_ALLOC_SIZE__ -D__HAVE_ATTRIBUTE_AUTO_TYPE__ -D__HAVE_ATTRIBUTE_BUILTIN_EXPECT__ -D__HAVE_ATTRIBUTE_BUILTIN_ISNAN__ -D__HAVE_ATTRIBUTE_CONST__ -D__HAVE_ATTRIBUTE_DEPRECATED__ -D__HAVE_ATTRIBUTE_GNU_PRINTF__ -D__HAVE_ATTRIBUTE_HOT__ -D__HAVE_ATTRIBUTE_MALLOC__ -D__HAVE_ATTRIBUTE_NONNULL__ -D__HAVE_ATTRIBUTE_NORETURN__ -D__HAVE_ATTRIBUTE_PACKED__ -D__HAVE_ATTRIBUTE_PURE__ -D__HAVE_ATTRIBUTE_RETURNS_NONNULL__ -D__HAVE_ATTRIBUTE_UNUSED__ -DGIT_REVISION=6895:20230518:1fb08c5af -DGIT_URL=git@gitlab-dhendriks:binary_c/binary_c.git -DGIT_BRANCH=releases/2.2.4 -D__HAVE_LIBC__ -D__HAVE_LIBCFITSIO__ -D__HAVE_LIBGSL__ -I/home/david/gsl/include -D__HAVE_LIBGSLCBLAS__ -D__HAVE_LIBDL__ -D__HAVE_LIBPTHREAD__ -D__HAVE_LIBUUID__ -D__HAVE_LIBZ__ -D__HAVE_LIBBACKTRACE__ -D__HAVE_LIBBZ2__ -D__HAVE_LIBCDICT__ -D__HAVE_LIBM__ -D__HAVE_LIBRINTERPOLATE__ -D__HAVE_BACKTRACE_H__ -D__HAVE_IEEE754_H__ -D__HAVE_DRAND48__ -D__HAVE_HSEARCH_DATA__ -D__HAVE_MALLOC_H__ -D__HAVE_SETITIMER__ -D__HAVE_HAS_INCLUDE -D__HAVE_PKG_CONFIG__ -D__HAVE_VALGRIND__ -D__SHOW_STARDATA__ -D__DIFF_STARDATA__ -D__HAVE_7Z__ -D__HAVE_BZCAT__ -D__HAVE_ZCAT__ -O0 -shared -D_SEARCH_H\n", "\tld = ld\n", "\tlibs = -L/home/david/projects/binary_c_root/binary_c/src -L/usr/lib/x86_64-linux-gnu -L/home/david/gsl/lib -L/home/david/projects/binary_c_root/robs_extra_packages/lib -L/home/david/projects/binary_c_root/binary_c/src -lc -lcfitsio -lpthread -lgsl -lgslcblas -lm -ldl -luuid -lz -lbacktrace -lbz2 -lcdict -lrinterpolate -lbinary_c\n", "\tinc = -I/home/david/projects/binary_c_root/binary_c -I/home/david/projects/binary_c_root/binary_c/src -I/home/david/projects/binary_c_root/robs_extra_packages/include -I/home/david/projects/binary_c_root/binary_c/src\n", "\n", "\n", "Building shared library for custom logging with (binary_c.h) on administrator-XPS-15-7590\n", "\n", "Executing following command to compile the shared library:\n", "cc -fPIC -std=gnu18 -DOPERATING_SYSTEM=linux -DLINUX -DPOSIX -DLARGEFILE_SOURCE -DMEMORY_ALLOCATION_MODEL=MEMORY_ALLOCATION_NATIVE -UALIGNSIZE -fstrict-aliasing -Wstrict-aliasing -g -Wno-sizeof-pointer-div -Wpedantic -Wshadow -Wno-variadic-macros -fstack-protector-all -rdynamic -fsignaling-nans -march=native -mtune=native -frounding-math -fno-stack-protector -ffloat-store -D__ACCURATE_BINARY_C__ -fno-finite-math-only -fasynchronous-unwind-tables -export-dynamic -O0 -DCPUFREQ=4500 -DBINARY_C_SRC=/home/david/projects/binary_c_root/binary_c/src -DPGO_off -DBINUTILS_VERSION=2.34 -DBFD_2_33 -D_FILE_OFFSET_BITS=64 -D__HAVE_LINK_H -D__HAVE__VA_OPT__ -D__HAVE_GNU_QSORT_R -D__HAVE_NATIVE_EXP10 -D__HAVE_POSIX_FADVISE -DFPU_CONTROL -D__HAVE_ATTRIBUTE___RESTRICT____ -D__HAVE_ATTRIBUTE_ALLOC_SIZE__ -D__HAVE_ATTRIBUTE_AUTO_TYPE__ -D__HAVE_ATTRIBUTE_BUILTIN_EXPECT__ -D__HAVE_ATTRIBUTE_BUILTIN_ISNAN__ -D__HAVE_ATTRIBUTE_CONST__ -D__HAVE_ATTRIBUTE_DEPRECATED__ -D__HAVE_ATTRIBUTE_GNU_PRINTF__ -D__HAVE_ATTRIBUTE_HOT__ -D__HAVE_ATTRIBUTE_MALLOC__ -D__HAVE_ATTRIBUTE_NONNULL__ -D__HAVE_ATTRIBUTE_NORETURN__ -D__HAVE_ATTRIBUTE_PACKED__ -D__HAVE_ATTRIBUTE_PURE__ -D__HAVE_ATTRIBUTE_RETURNS_NONNULL__ -D__HAVE_ATTRIBUTE_UNUSED__ -DGIT_REVISION=6895:20230518:1fb08c5af -DGIT_URL=git@gitlab-dhendriks:binary_c/binary_c.git -DGIT_BRANCH=releases/2.2.4 -D__HAVE_LIBC__ -D__HAVE_LIBCFITSIO__ -D__HAVE_LIBGSL__ -I/home/david/gsl/include -D__HAVE_LIBGSLCBLAS__ -D__HAVE_LIBDL__ -D__HAVE_LIBPTHREAD__ -D__HAVE_LIBUUID__ -D__HAVE_LIBZ__ -D__HAVE_LIBBACKTRACE__ -D__HAVE_LIBBZ2__ -D__HAVE_LIBCDICT__ -D__HAVE_LIBM__ -D__HAVE_LIBRINTERPOLATE__ -D__HAVE_BACKTRACE_H__ -D__HAVE_IEEE754_H__ -D__HAVE_DRAND48__ -D__HAVE_HSEARCH_DATA__ -D__HAVE_MALLOC_H__ -D__HAVE_SETITIMER__ -D__HAVE_HAS_INCLUDE -D__HAVE_PKG_CONFIG__ -D__HAVE_VALGRIND__ -D__SHOW_STARDATA__ -D__DIFF_STARDATA__ -D__HAVE_7Z__ -D__HAVE_BZCAT__ -D__HAVE_ZCAT__ -O0 -shared -D_SEARCH_H -L/home/david/projects/binary_c_root/binary_c/src -L/usr/lib/x86_64-linux-gnu -L/home/david/gsl/lib -L/home/david/projects/binary_c_root/robs_extra_packages/lib -L/home/david/projects/binary_c_root/binary_c/src -lc -lcfitsio -lpthread -lgsl -lgslcblas -lm -ldl -luuid -lz -lbacktrace -lbz2 -lcdict -lrinterpolate -lbinary_c -o /tmp/binary_c_python-david/notebooks/notebook_comenv/custom_logging/libcustom_logging_c2c13e8068bc4385b960647d0028913e.so /tmp/binary_c_python-david/notebooks/notebook_comenv/custom_logging/custom_logging.c -I/home/david/projects/binary_c_root/binary_c -I/home/david/projects/binary_c_root/binary_c/src -I/home/david/projects/binary_c_root/robs_extra_packages/include -I/home/david/projects/binary_c_root/binary_c/src\n", "loading shared library for custom logging\n", "loaded shared library for custom logging. custom_output_function is loaded in memory at 140439734821610\n", "Write grid code to /tmp/binary_c_python-david/notebooks/notebook_comenv/binary_c_grid_9826c6516bf44709b625ec9ff93c43ed.py [dry_run = True]\n", "Doing a dry run of the grid.\n", "Grid has handled 729 stars with a total probability of 0.0645564\n", "\n", "**********************************\n", "* Dry run *\n", "* Total starcount is 729 *\n", "* Total probability is 0.0645564 *\n", "**********************************\n", "\n", "setting up the system_queue_filler now\n", "Write grid code to /tmp/binary_c_python-david/notebooks/notebook_comenv/binary_c_grid_9826c6516bf44709b625ec9ff93c43ed.py [dry_run = False]\n", "Signalling processes to stop\n", "\n", "95/729 13.0% complete 18:25:37 ETA= 1.1m tpr=4.22e-01 ETF=18:26:44 mem:754.9MB M1=1.3 M2=1.1 P=3.2e+2\n", "\n", "162/729 22.2% complete 18:25:48 ETA= 1.4m tpr=6.09e-01 ETF=18:27:14 mem:516.0MB M1=1.6 M2=1 P=2.3\n", "\n", "287/729 39.4% complete 18:25:58 ETA= 1.1m tpr=6.09e-01 ETF=18:27:05 mem:516.6MB M1=2 M2=1.5 P=6.1e+3\n", "\n", "426/729 58.4% complete 18:26:08 ETA= 31.9s tpr=4.21e-01 ETF=18:26:39 mem:518.6MB M1=3 M2=1.6 P=44\n", "\n", "554/729 76.0% complete 18:26:18 ETA= 16.0s tpr=3.65e-01 ETF=18:26:34 mem:520.0MB M1=3.6 M2=3.2 P=3.2e+2\n", "\n", "677/729 92.9% complete 18:26:28 ETA= 4.6s tpr=3.51e-01 ETF=18:26:32 mem:520.5MB M1=5.4 M2=2.7 P=17\n", "\n", "****************************************************\n", "* Process 2 finished: *\n", "* generator started at 2023-05-18T18:25:29.908382 *\n", "* generator finished at 2023-05-18T18:26:34.001016 *\n", "* total: 1 minute and 4.09s *\n", "* of which 1 minute and 3.85s with binary_c *\n", "* Ran 188 systems *\n", "* with a total probability of 0.0166562 *\n", "* This thread had 0 failing systems *\n", "* with a total failed probability of 0 *\n", "* Skipped a total of 0 zero-probability systems *\n", "* *\n", "****************************************************\n", "\n", "\n", "****************************************************\n", "* Process 3 finished: *\n", "* generator started at 2023-05-18T18:25:29.919454 *\n", "* generator finished at 2023-05-18T18:26:34.127644 *\n", "* total: 1 minute and 4.21s *\n", "* of which 1 minute and 3.94s with binary_c *\n", "* Ran 185 systems *\n", "* with a total probability of 0.0160873 *\n", "* This thread had 0 failing systems *\n", "* with a total failed probability of 0 *\n", "* Skipped a total of 0 zero-probability systems *\n", "* *\n", "****************************************************\n", "\n", "\n", "****************************************************\n", "* Process 0 finished: *\n", "* generator started at 2023-05-18T18:25:29.891799 *\n", "* generator finished at 2023-05-18T18:26:35.859784 *\n", "* total: 1 minute and 5.97s *\n", "* of which 1 minute and 5.74s with binary_c *\n", "* Ran 185 systems *\n", "* with a total probability of 0.0168338 *\n", "* This thread had 0 failing systems *\n", "* with a total failed probability of 0 *\n", "* Skipped a total of 0 zero-probability systems *\n", "* *\n", "****************************************************\n", "\n", "\n", "****************************************************\n", "* Process 1 finished: *\n", "* generator started at 2023-05-18T18:25:29.898577 *\n", "* generator finished at 2023-05-18T18:26:36.222228 *\n", "* total: 1 minute and 6.32s *\n", "* of which 1 minute and 6.11s with binary_c *\n", "* Ran 171 systems *\n", "* with a total probability of 0.014979 *\n", "* This thread had 0 failing systems *\n", "* with a total failed probability of 0 *\n", "* Skipped a total of 0 zero-probability systems *\n", "* *\n", "****************************************************\n", "\n", "\n", "************************************************************************\n", "* Population-9826c6516bf44709b625ec9ff93c43ed finished! *\n", "* The total probability is 0.0645564. *\n", "* It took a total of 1 minute and 6.85s to run 729 systems on 4 cores *\n", "* = 4m 27.41s of CPU time. *\n", "* Maximum memory use 754.891 MB *\n", "************************************************************************\n", "\n", "No failed systems were found in this run.\n" ] } ], "source": [ "# set number of threads\n", "population.set(\n", " # set number of threads (i.e. number of CPU cores we use)\n", " num_cores=4,\n", " verbosity=VERBOSITY\n", ")\n", "\n", "# Evolve the population - this is the slow, number-crunching step\n", "analytics = population.evolve() \n", "\n", "# Show the results (debugging)\n", "#print (population.population_results)" ] }, { "cell_type": "markdown", "id": "91ab45c7-7d31-4543-aee4-127ab58e891f", "metadata": {}, "source": [ "After the run is complete, some technical report on the run is returned. I store that in `analytics`. As we can see below, this dictionary is like a status report of the evolution. Useful for e.g. debugging. We check this, and then set about making the plot of the orbital period distributions using Seaborn." ] }, { "cell_type": "code", "execution_count": 7, "id": "e1f0464b-0424-4022-b34b-5b744bc2c59d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'population_id': '9826c6516bf44709b625ec9ff93c43ed', 'evolution_type': 'grid', 'failed_count': 0, 'failed_prob': 0, 'failed_systems_error_codes': [], 'errors_exceeded': False, 'errors_found': False, 'total_probability': 0.0645563923306419, 'total_count': 729, 'start_timestamp': 1684430729.8425448, 'end_timestamp': 1684430796.6938975, 'time_elapsed': 66.85135269165039, 'total_mass_run': 3410.936346584559, 'total_probability_weighted_mass_run': 0.22609060418511753, 'zero_prob_stars_skipped': 0}\n" ] } ], "source": [ "print(analytics)" ] }, { "cell_type": "code", "execution_count": 8, "id": "05c6d132-abee-423e-b1a8-2039c8996fbc", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0, 0.5, 'Number of stars')" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# make a plot of the distributions\n", "import seaborn as sns\n", "import pandas as pd\n", "import copy\n", "\n", "from binarycpython.utils.functions import pad_output_distribution\n", "\n", "pd.set_option(\"display.max_rows\", None, \"display.max_columns\", None)\n", "\n", "\n", "# set up seaborn for use in the notebook\n", "sns.set(rc={'figure.figsize':(20,10)})\n", "sns.set_context(\"notebook\",\n", " font_scale=1.5,\n", " rc={\"lines.linewidth\":2.5})\n", "\n", "# remove the merged objects\n", "probability = { \"merged\" : 0.0, \"unmerged\" : 0.0}\n", "\n", "# copy the results so we can change the copy\n", "results = copy.deepcopy(population.population_results)\n", "\n", "for distribution in ['post']: \n", " for logper in population.population_results[distribution]:\n", " dprob = results[distribution][logper]\n", " if logper < -90:\n", " # merged system\n", " probability[\"merged\"] += dprob\n", " del results[distribution][logper]\n", " else:\n", " # unmerged system\n", " probability[\"unmerged\"] += dprob\n", " \n", "# pad the final distribution with zero\n", "for distribution in population.population_results: \n", " pad_output_distribution(results[distribution],\n", " binwidth)\n", " \n", "# make pandas dataframe \n", "plot_data = pd.DataFrame.from_dict(results, orient='columns')\n", "\n", "# make the plot\n", "p = sns.lineplot(data=plot_data)\n", "p.set_xlabel(\"$\\log_{10} (P_\\mathrm{orb} / \\mathrm{day})$\")\n", "p.set_ylabel(\"Number of stars\")" ] }, { "cell_type": "markdown", "id": "c4740c93-d01e-4ca1-8766-c2fb4ddca2e4", "metadata": {}, "source": [ "You can see that common-envelope evolution shrinks stellar orbits, just as we expect. Pre-CEE, most orbits are in the range $10$ to $1000\\text{ }\\mathrm{d}$, while after CEE the distribution peaks at about $1\\text{ }\\mathrm{d}$. Some of these orbits are very short: $\\log_{10}(-2) = 0.01\\text{ }\\mathrm{d}\\sim10\\text{ }\\mathrm{minutes}$. Such systems are prime candidates for exciting astrophysics: novae, type Ia supernovae and gravitational wave sources." ] }, { "cell_type": "markdown", "id": "57faf043-3809-427a-b378-2355ce8c2691", "metadata": {}, "source": [ "Things to try:\n", "\n", " * Extend the logging to output more data than just the orbital period.\n", " * What are the stellar types of the post-common envelope systems? Are they likely to undergo novae or a type-Ia supernova?\n", " * What are the lifetimes of the systems in close ($<1\\text{ }\\mathrm{d}$) binaries? Are they likely to merge in the life of the Universe?\n", " * How much mass is lost in common-envelope interactions?\n", " * Extend the grid to massive stars. Do you see many NS and BH compact binaries?\n", " * Try different $\\alpha_\\mathrm{CE}$ and $\\lambda_\\mathrm{CE}$ options...\n", " * ... and perhaps increased resolution to obtain smoother curves.\n", " * Why do long-period systems not reach common envelope evolution?\n", " " ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.9" } }, "nbformat": 4, "nbformat_minor": 5 }